#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/AST.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CodeGen/CodeGenAction.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/TargetSelect.h"

using namespace clang;
using namespace llvm;

class MyASTConsumer : public ASTConsumer {
	public:
		virtual bool HandleTopLevelDecl(DeclGroupRef DG) override {
			for (auto D : DG) {
				if (auto FD = dyn_cast<FunctionDecl>(D)) {
					FD->dump();
				}
			}
			return true;
		}
};

class MyFrontendAction : public ASTFrontendAction {
	public:
		virtual std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, StringRef file) override {
			return std::make_unique<MyASTConsumer>();
		}
};

int main(int argc, const char **argv) {
	InitializeNativeTarget();
	InitializeNativeTargetAsmPrinter();

	CompilerInstance CI;
	CI.createDiagnostics();

	std::shared_ptr<clang::TargetOptions> TO = std::make_shared<clang::TargetOptions>();
	TO->Triple = llvm::sys::getDefaultTargetTriple();
	TargetInfo *TI = TargetInfo::CreateTargetInfo(CI.getDiagnostics(), TO);
	CI.setTarget(TI);

	CI.createFileManager();
	CI.createSourceManager(CI.getFileManager());
	CI.createPreprocessor(clang::TU_Module);
	CI.createASTContext();

	std::vector<const char *> Args(argv + 1, argv + argc);
	clang::CompilerInvocation::CreateFromArgs(CI.getInvocation(), Args, CI.getDiagnostics());
	CI.createASTContext();

	MyFrontendAction action;
	if (!CI.ExecuteAction(action)) {
		return 1;
	}

	return 0;
}
